home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Documentation / d e v e l o p / Develop Issue 23 article / Geometry Sample / Shell src / DragSupport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  8.6 KB  |  317 lines  |  [TEXT/MPS ]

  1. #include "BuildControl.h"
  2.  
  3.  
  4.  
  5. #if defined(qUseDumpFile)
  6.     #include "DumpHeader.h"
  7. #else
  8.     #include <Resources.h>
  9. #endif
  10.  
  11. #include "DragSupport.h"
  12.  
  13. DragHandlerGlobals pDragGlobals;
  14.  
  15. //-----------------------------------------------------------------------
  16.  
  17. Boolean DragMgrPresent(void)
  18. {
  19.     OSErr    err;
  20.     long    response = 0L;
  21.     
  22.     err = Gestalt(gestaltDragMgrAttr, &response);
  23.     
  24.     if ((err == noErr) 
  25.         && (response && (1 << gestaltDragMgrPresent) != 0))
  26.         return true;
  27.  
  28.     else
  29.         return false;                 
  30. }
  31.  
  32. //-----------------------------------------------------------------------
  33. // InstallDragHandlers attaches my tracking and receive handlers to
  34. // one of the application's windows
  35. //-----------------------------------------------------------------------
  36. OSErr InstallDragHandlers(WindowPtr win)
  37. {    
  38.     OSErr     err;
  39.     
  40.     if (DragMgrPresent()) {
  41.         err = InstallTrackingHandler((DragTrackingHandler) DragTracker, win, nil);
  42.         if (err != noErr) goto Bail;    
  43.     
  44.         err = InstallReceiveHandler((DragReceiveHandler) DragReceiver, win, nil);
  45.         if (err != noErr) 
  46.             (void) RemoveTrackingHandler((DragTrackingHandler) DragTracker, win);
  47.     }
  48.  
  49. Bail:    
  50.     return err;
  51. }
  52.  
  53. //-----------------------------------------------------------------------
  54. // RemoveDragHandlers removes my tracking and receive handlers from
  55. // one of the application's windows (prior to the window's disposal,
  56. // presumably)
  57. //-----------------------------------------------------------------------
  58. void RemoveDragHandlers(WindowPtr win)
  59. {
  60.     if (DragMgrPresent()) {
  61.         RemoveReceiveHandler((DragReceiveHandler) DragReceiver, win);
  62.         RemoveTrackingHandler((DragTrackingHandler) DragTracker, win);
  63.     }
  64. }
  65.  
  66. //-----------------------------------------------------------------------
  67. // DragItemsAreAcceptable returns true if the contents (data) of
  68. // the drag is only a 'TEXT' flavor.
  69. //
  70. // DragItemsAreAcceptable is called by the tracking and receive handlers
  71. //-----------------------------------------------------------------------
  72. Boolean DragItemsAreAcceptable(DragReference drag)
  73. {
  74.     OSErr            err;
  75.     unsigned short    totalItems;
  76.     ItemReference    itemRef;
  77.     Boolean            acceptIt;
  78.     Ptr                 textFlavor;
  79.     Size            dataSize;
  80.     
  81.     acceptIt = false;
  82.     err = CountDragItems(drag, &totalItems);
  83.  
  84.     if ((err == noErr) && (totalItems == 1))  {
  85.         //
  86.         // Only accept the drag if there's only one flavor, and
  87.         // its a TEXT one.
  88.         //
  89.         err = GetDragItemReferenceNumber(drag, 1, &itemRef);
  90.         if (err != noErr)    goto Bail;
  91.         
  92.         err = GetFlavorDataSize(drag, 1, 'TEXT', &dataSize);
  93.         if (err != noErr) goto Bail;
  94.  
  95.         textFlavor = NewPtr(dataSize);
  96.         if (textFlavor == NULL) goto Bail;
  97.         
  98.         err = GetFlavorData(drag, itemRef, 'TEXT', textFlavor, &dataSize, 0);
  99.         if (err == noErr) acceptIt = true;
  100.         
  101.         DisposePtr(textFlavor);
  102.     }
  103.  
  104. Bail:
  105.     return acceptIt;
  106. }
  107.  
  108. //-----------------------------------------------------------------------
  109. // DragIsNotInSourceWindow returns true if the drag in progress
  110. // is not in the same window it originated in
  111. // 
  112. // DragIsNotInSourceWindow is called by the tracking and receive handlers
  113. // 
  114. // Note that, if this application allowed items to be dragged within
  115. // its windows, this function would not be appropriate.
  116. // Instead, hilighting would probably occur in the source window
  117. // when the dragHasLeftSourceWindow flag is set, and the receive
  118. // handler wouldn't check this at all
  119. //-----------------------------------------------------------------------
  120. Boolean DragIsNotInSourceWindow(DragReference drag)
  121. {
  122.     DragAttributes currDragFlags;
  123.     
  124.     (void) GetDragAttributes(drag, &currDragFlags);
  125.     return ((currDragFlags & dragInsideSenderWindow) == 0);
  126. }
  127.  
  128. //-----------------------------------------------------------------------
  129. // DragTracker is called by the drag manager whenever a drag is
  130. // over one of the application's windows
  131. //
  132. // upon entry, the current port has been set to win by the Drag Manager
  133. //-----------------------------------------------------------------------
  134. pascal OSErr DragTracker(DragTrackingMessage message, WindowPtr win,
  135.     void *handlerRefCon, DragReference drag)
  136. {
  137. #pragma unused (handlerRefCon)
  138.     RgnHandle            tempRgn;
  139.     Rect                rct, emptyRect = {0,0,0,0};
  140.     OSErr                err = noErr;
  141.     
  142.     switch (message) {
  143.         case dragTrackingEnterHandler:
  144.             //
  145.             // Determine if the items are acceptable and store that 
  146.             // flag in the globals, plus reset the hilighted global flag
  147.             //
  148.             pDragGlobals.acceptableDragFlag = DragItemsAreAcceptable(drag);
  149.             pDragGlobals.currDragRect = emptyRect;
  150.             if (!pDragGlobals.acceptableDragFlag)
  151.                 err = dragNotAcceptedErr;
  152.             break;
  153.             
  154.         case dragTrackingEnterWindow: 
  155.         case dragTrackingInWindow:
  156.         case dragTrackingLeaveWindow:
  157.             
  158.             // Highlighting of the window during a drag is done
  159.             // here.  Do it only if we can accept these items
  160.             // and we're not in the source window...
  161.             if (pDragGlobals.acceptableDragFlag && DragIsNotInSourceWindow(drag)) {
  162.                 //
  163.                 // Unless the mouse is leaving the visible area of the
  164.                 // window, check if it's in the window's content region
  165.                 //
  166.                 if (message == dragTrackingLeaveWindow)
  167.                     rct = emptyRect;
  168.                 else
  169.                     rct = win->portRect;
  170.                 
  171.                 //
  172.                 // If the mouse is in the content area and the window
  173.                 // is not yet hilighted, then do the hilighting
  174.                 //
  175.                 if (!EmptyRect(&rct) 
  176.                     && !EqualRect(&pDragGlobals.currDragRect, &rct)) {
  177.                     ClipRect(&win->portRect);
  178.                     tempRgn = NewRgn();
  179.                     RectRgn(tempRgn, &rct);
  180.                 
  181.                     if (ShowDragHilite(drag, tempRgn, true) == noErr)                    
  182.                         //
  183.                         // Remember that hilighting is now on
  184.                         //
  185.                         pDragGlobals.currDragRect = rct;                    
  186.                     
  187.                     DisposeRgn(tempRgn);
  188.                 }
  189.                 //
  190.                 // Else if the mouse is not in the content region
  191.                 // and the window is hilighted, erase the hilight
  192.                 //
  193.                 else if (EmptyRect(&rct) 
  194.                     && !EqualRect(&pDragGlobals.currDragRect, &emptyRect)) {
  195.                      ClipRect(&win->portRect);
  196.  
  197.                     if (HideDragHilite(drag) == noErr)
  198.                         //                    
  199.                         // Remember that hilighting is now off
  200.                         //
  201.                         pDragGlobals.currDragRect = emptyRect;
  202.                 }
  203.             }
  204.             break;
  205.  
  206.         case dragTrackingLeaveHandler:
  207.             break;
  208.         
  209.         default:
  210.             err = paramErr;
  211.     }
  212.     
  213.     return err;
  214. }
  215.  
  216. //-----------------------------------------------------------------------
  217. // DragReceiver is called by the drag manager whenever a drag is
  218. // ends on one of the application's windows
  219. //-----------------------------------------------------------------------
  220. pascal OSErr DragReceiver(WindowPtr win, void *handlerRefCon, 
  221.         DragReference drag)
  222. {
  223. #pragma unused (handlerRefCon, win)
  224.     ItemReference    itemRef;
  225.     Size            dataSize;
  226.     Ptr                textFlavor;
  227.     OSErr            err = noErr;
  228.     unsigned short    numItems, counter;
  229.     
  230.     if (!DragItemsAreAcceptable(drag) || !DragIsNotInSourceWindow(drag)) 
  231.         return dragNotAcceptedErr;
  232.  
  233.     CountDragItems(drag, &numItems);
  234.     
  235.     for (counter = 1; counter <= numItems; counter++) {
  236.         err = GetDragItemReferenceNumber(drag, counter, &itemRef);
  237.         if (err != noErr)  goto BailOut;
  238.         
  239.         err = GetFlavorDataSize(drag, itemRef, 'TEXT', &dataSize);
  240.         if (err != noErr) goto BailOut;
  241.  
  242.         textFlavor = NewPtr(dataSize);
  243.         if (textFlavor == NULL) goto BailOut;
  244.  
  245.         err = GetFlavorData(drag, itemRef, 'TEXT', textFlavor, &dataSize, 0);
  246.         if (err == noErr) {
  247.             //
  248.             // The drag was successful.  Do whatever you want with the data.
  249.             //
  250.             SysBeep(20);
  251.             DisposePtr(textFlavor);
  252.         }
  253.     }
  254.  
  255. BailOut:
  256.     return err;
  257. }
  258.  
  259. //-----------------------------------------------------------------------
  260. // OutlineRegion changes a region into a tracing of its border
  261. // which is appropriate for normal dragging
  262. //-----------------------------------------------------------------------
  263. void OutlineRegion(RgnHandle theRgn)
  264. {
  265.     RgnHandle tempRgn;
  266.     
  267.     tempRgn = NewRgn();
  268.     CopyRgn(theRgn, tempRgn);
  269.     InsetRgn(tempRgn, 1, 1);
  270.     DiffRgn(theRgn, tempRgn, theRgn);
  271.     DisposeRgn(tempRgn);
  272. }
  273.  
  274. //-----------------------------------------------------------------------
  275.  
  276. OSErr AddTextFlavor(DragReference drag, ItemReference item, StringPtr str)
  277. {
  278.     return AddDragItemFlavor(drag, item, 'TEXT', &str[1], str[0], 0);
  279. }
  280.  
  281. //-----------------------------------------------------------------------
  282.  
  283. OSErr StartDrag(WindowPtr win, EventRecord *event)
  284. {
  285.     OSErr            err;
  286.     DragReference    drag;
  287.     Rect            dragBounds;
  288.     RgnHandle        dragRgn;
  289.     ItemReference    item = 1;
  290.  
  291.     err = NewDrag(&drag);
  292.     if (err != noErr) goto Bail;
  293.     
  294.     err = AddTextFlavor(drag, item, "\pInitial Add");
  295.     if (err != noErr) goto DisposeDragAndBail;
  296.     
  297.     //
  298.     // Generate the bounds and region for the drag using the window's
  299.     // content rectangle
  300.     //
  301.     dragBounds = (**((WindowPeek) win)->contRgn).rgnBBox;
  302.     err = SetDragItemBounds(drag, item, &dragBounds);
  303.     if (err != noErr) goto DisposeDragAndBail;
  304.     
  305.     dragRgn = NewRgn();
  306.     RectRgn(dragRgn, &dragBounds);
  307.     OutlineRegion(dragRgn);
  308.     err = TrackDrag(drag, event, dragRgn);    
  309.     DisposeRgn(dragRgn);
  310.     
  311. DisposeDragAndBail:
  312.     DisposeDrag(drag);
  313.  
  314. Bail:
  315.     return err;
  316. }
  317.